package com.course.model.service;

import com.alibaba.fastjson.JSON;
import com.course.model.dto.LoginUserDto;
import com.course.model.dto.ResourceDto;
import com.course.model.entity.User;
import com.course.model.entity.UserExample;
import com.course.model.dto.UserDto;
import com.course.model.dto.PageDto;
import com.course.model.exception.BusinessException;
import com.course.model.exception.BusinessExceptionCode;
import com.course.model.mapper.UserMapper;
import com.course.model.mapper.my.MyUserMapper;
import com.course.model.util.CopyUtil;
import com.course.model.util.UuidUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;

@Service
public class UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    @Resource
    private UserMapper userMapper;

    @Resource
    private BCryptPasswordEncoder encoder;

    @Resource
    private MyUserMapper myUserMapper;

    /**
     * 列表查询
     */
    public void list(PageDto pageDto) {
        PageHelper.startPage(pageDto.getPage(), pageDto.getSize());
        UserExample userExample = new UserExample();
        List<User> userList = userMapper.selectByExample(userExample);
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        pageDto.setTotal(pageInfo.getTotal());
        List<UserDto> userDtoList = CopyUtil.copyList(userList, UserDto.class);
        pageDto.setList(userDtoList);
    }

    /**
     * 保存，id有值时更新，无值时新增
     */
    public void save(UserDto userDto) {
        User user = CopyUtil.copy(userDto, User.class);
        if (StringUtils.isBlank(userDto.getId())) {
            this.insert(user);
        } else {
            this.update(user);
        }
    }

    /**
     * 新增
     */
    private void insert(User user) {
        user.setId(UuidUtil.getShortUuid());
        Optional<User> optional = Optional.ofNullable(this.selectByLoginName(user.getLoginName()));
        if (optional.isPresent()) {
            throw new BusinessException(BusinessExceptionCode.USER_LOGIN_NAME_EXIST);
        } else {
            userMapper.insert(user);
        }
    }

    /**
     * 更新
     */
    private void update(User user) {
        user.setPassword(null);
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 删除
     */
    public void delete(String id) {
        userMapper.deleteByPrimaryKey(id);
    }

    /**
     * 根据登录名查询用户记录
     *
     * @param loginName
     * @return
     */
    public User selectByLoginName(String loginName) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        criteria.andLoginNameEqualTo(loginName);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) {
            return null;
        } else {
            return users.get(0);
        }
    }

    /**
     * 重置密码
     * @param userDto
     */
    public void savePassword(UserDto userDto){
        User user = new User();
        user.setId(userDto.getId());
        user.setPassword(userDto.getPassword());
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 用户登录
     * @param userDto
     */
    public LoginUserDto login(UserDto userDto){
        Optional<User> userDb = Optional.ofNullable(selectByLoginName(userDto.getLoginName()));
        if (userDb.isPresent()){
            if (encoder.matches(userDto.getPassword(),userDb.get().getPassword())){
                //登录成功
                LoginUserDto loginUserDto = CopyUtil.copy(userDb.get(), LoginUserDto.class);

                //使用redisson-发布订阅组件，异步记录用户登录成功后的信息

                //为登录用户读取权限
                setAuth(loginUserDto);
                return loginUserDto;
            } else {
                logger.info("密码输入有误，输入密码：{},数据库密码：{}",userDto.getPassword(),userDb.get().getPassword());
                throw new BusinessException(BusinessExceptionCode.LOGIN_USER_ERROR);
            }
        } else {
            logger.info("用户名不存在：{}",userDto.getLoginName());
            throw new BusinessException(BusinessExceptionCode.LOGIN_USER_ERROR);
        }
    }

    /**
     * 为登录用户读取权限
     * @param loginUserDto
     */
    private void setAuth(LoginUserDto loginUserDto){
        List<ResourceDto> resources = myUserMapper.findResources(loginUserDto.getId());
        loginUserDto.setResources(resources);

        //整理所有权限的请求，用于接口拦截
        HashSet<String> requestSet = new HashSet<>();
        if (!CollectionUtils.isEmpty(resources)){
            for (int i = 0; i < resources.size(); i++) {
                ResourceDto resourceDto = resources.get(i);
                String arrayString = resourceDto.getRequest();
                List<String> requestList = JSON.parseArray(arrayString, String.class);
                if (!CollectionUtils.isEmpty(requestList)){
                    requestSet.addAll(requestList);
                }
            }
        }
        logger.info("有权限的请求：{}",requestSet);
        loginUserDto.setRequests(requestSet);
    }
}
